home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / system / source / filesys.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-10-13  |  18.4 KB  |  631 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #include "stdafx.h"
  27. #include <ctype.h>
  28. #include <string.h>
  29.  
  30. #include <vd2/system/VDString.h>
  31. #include <vd2/system/filesys.h>
  32. #include <vd2/system/Error.h>
  33. #include <vd2/system/vdstl.h>
  34.  
  35. ///////////////////////////////////////////////////////////////////////////
  36.  
  37. template<class T, class U>
  38. static inline T splitimpL(const T& string, const U *s) {
  39.     const U *p = string.c_str();
  40.     return T(p, s - p);
  41. }
  42.  
  43. template<class T, class U>
  44. static inline T splitimpR(const T& string, const U *s) {
  45.     const U *p = string.c_str();
  46.     return T(s);
  47. }
  48.  
  49. ///////////////////////////////////////////////////////////////////////////
  50.  
  51. const char *VDFileSplitFirstDir(const char *s) {
  52.     const char *start = s;
  53.  
  54.     while(*s++)
  55.         if (s[-1] == ':' || s[-1] == '\\' || s[-1] == '/')
  56.             return s;
  57.  
  58.     return start;
  59. }
  60.  
  61. const wchar_t *VDFileSplitFirstDir(const wchar_t *s) {
  62.     const wchar_t *start = s;
  63.  
  64.     while(*s++)
  65.         if (s[-1] == L':' || s[-1] == L'\\' || s[-1] == L'/')
  66.             return s;
  67.  
  68.     return start;
  69. }
  70.  
  71. const char *VDFileSplitPath(const char *s) {
  72.     const char *lastsep = s;
  73.  
  74.     while(*s++)
  75.         if (s[-1] == ':' || s[-1] == '\\' || s[-1] == '/')
  76.             lastsep = s;
  77.  
  78.     return lastsep;
  79. }
  80.  
  81. const wchar_t *VDFileSplitPath(const wchar_t *s) {
  82.     const wchar_t *lastsep = s;
  83.  
  84.     while(*s++)
  85.         if (s[-1] == L':' || s[-1] == L'\\' || s[-1] == L'/')
  86.             lastsep = s;
  87.  
  88.     return lastsep;
  89. }
  90.  
  91. VDString  VDFileSplitPathLeft (const VDString&  s) { return splitimpL(s, VDFileSplitPath(s.c_str())); }
  92. VDStringW VDFileSplitPathLeft (const VDStringW& s) { return splitimpL(s, VDFileSplitPath(s.c_str())); }
  93. VDString  VDFileSplitPathRight(const VDString&  s) { return splitimpR(s, VDFileSplitPath(s.c_str())); }
  94. VDStringW VDFileSplitPathRight(const VDStringW& s) { return splitimpR(s, VDFileSplitPath(s.c_str())); }
  95.  
  96. const char *VDFileSplitRoot(const char *s) {
  97.     // Test for a UNC path.
  98.     if (s[0] == '\\' && s[1] == '\\') {
  99.         // For these, we scan for the fourth backslash.
  100.         s += 2;
  101.         for(int i=0; i<2; ++i) {
  102.             while(*s && *s != '\\')
  103.                 ++s;
  104.             if (*s == '\\')
  105.                 ++s;
  106.         }
  107.         return s;
  108.     }
  109.  
  110.     const char *const t = s;
  111.  
  112.     while(*s && *s != ':' && *s != '/' && *s != '\\')
  113.         ++s;
  114.  
  115.     return *s ? *s == ':' && (s[1]=='/' || s[1]=='\\') ? s+2 : s+1 : t;
  116. }
  117.  
  118. const wchar_t *VDFileSplitRoot(const wchar_t *s) {
  119.     // Test for a UNC path.
  120.     if (s[0] == '\\' && s[1] == '\\') {
  121.         // For these, we scan for the fourth backslash.
  122.         s += 2;
  123.         for(int i=0; i<2; ++i) {
  124.             while(*s && *s != '\\')
  125.                 ++s;
  126.             if (*s == '\\')
  127.                 ++s;
  128.         }
  129.         return s;
  130.     }
  131.  
  132.     const wchar_t *const t = s;
  133.  
  134.     while(*s && *s != L':' && *s != L'/' && *s != L'\\')
  135.         ++s;
  136.  
  137.     return *s ? *s == L':' && (s[1]==L'/' || s[1]==L'\\') ? s+2 : s+1 : t;
  138. }
  139.  
  140. VDString  VDFileSplitRoot(const VDString&  s) { return splitimpL(s, VDFileSplitRoot(s.c_str())); }
  141. VDStringW VDFileSplitRoot(const VDStringW& s) { return splitimpL(s, VDFileSplitRoot(s.c_str())); }
  142.  
  143. const char *VDFileSplitExt(const char *s) {
  144.     const char *t = s;
  145.  
  146.     while(*t)
  147.         ++t;
  148.  
  149.     const char *const end = t;
  150.  
  151.     while(t>s) {
  152.         --t;
  153.  
  154.         if (*t == '.')
  155.             return t;
  156.  
  157.         if (*t == ':' || *t == '\\' || *t == '/')
  158.             break;
  159.     }
  160.  
  161.     return NULL;
  162. }
  163.  
  164. const wchar_t *VDFileSplitExt(const wchar_t *s) {
  165.     const wchar_t *t = s;
  166.  
  167.     while(*t)
  168.         ++t;
  169.  
  170.     const wchar_t *const end = t;
  171.  
  172.     while(t>s) {
  173.         --t;
  174.  
  175.         if (*t == L'.')
  176.             return t;
  177.  
  178.         if (*t == L':' || *t == L'\\' || *t == L'/')
  179.             break;
  180.     }
  181.  
  182.     return end;
  183. }
  184.  
  185. VDString  VDFileSplitExtLeft (const VDString&  s) { return splitimpL(s, VDFileSplitExt(s.c_str())); }
  186. VDStringW VDFileSplitExtLeft (const VDStringW& s) { return splitimpL(s, VDFileSplitExt(s.c_str())); }
  187. VDString  VDFileSplitExtRight(const VDString&  s) { return splitimpR(s, VDFileSplitExt(s.c_str())); }
  188. VDStringW VDFileSplitExtRight(const VDStringW& s) { return splitimpR(s, VDFileSplitExt(s.c_str())); }
  189.  
  190. /////////////////////////////////////////////////////////////////////////////
  191.  
  192. bool VDFileWildMatch(const char *pattern, const char *path) {
  193.     // What we do here is split the string into segments that are bracketed
  194.     // by sequences of asterisks. The trick is that the first match for a
  195.     // segment as the best possible match, so we can continue. So we just
  196.     // take each segment at a time and walk it forward until we find the
  197.     // first match or we fail.
  198.     //
  199.     // Time complexity is O(NM), where N=length of string and M=length of
  200.     // the pattern. In practice, it's rather fast.
  201.  
  202.     bool star = false;
  203.     int i = 0;
  204.     for(;;) {
  205.         char c = (char)tolower((unsigned char)pattern[i]);
  206.         if (c == '*') {
  207.             star = true;
  208.             pattern += i+1;
  209.             if (!*pattern)
  210.                 return true;
  211.             path += i;
  212.             i = 0;
  213.             continue;
  214.         }
  215.  
  216.         char d = (char)tolower((unsigned char)path[i]);
  217.         ++i;
  218.  
  219.         if (c == '?') {        // ? matches any character but null.
  220.             if (!d)
  221.                 return false;
  222.         } else if (c != d) {    // Literal character must match itself.
  223.             // If we're at the end of the string or there is no
  224.             // previous asterisk (anchored search), there's no other
  225.             // match to find.
  226.             if (!star || !d || !i)
  227.                 return false;
  228.  
  229.             // Restart segment search at next position in path.
  230.             ++path;
  231.             i = 0;
  232.             continue;
  233.         }
  234.  
  235.         if (!c)
  236.             return true;
  237.     }
  238. }
  239.  
  240. bool VDFileWildMatch(const wchar_t *pattern, const wchar_t *path) {
  241.     // What we do here is split the string into segments that are bracketed
  242.     // by sequences of asterisks. The trick is that the first match for a
  243.     // segment as the best possible match, so we can continue. So we just
  244.     // take each segment at a time and walk it forward until we find the
  245.     // first match or we fail.
  246.     //
  247.     // Time complexity is O(NM), where N=length of string and M=length of
  248.     // the pattern. In practice, it's rather fast.
  249.  
  250.     bool star = false;
  251.     int i = 0;
  252.     for(;;) {
  253.         wchar_t c = towlower(pattern[i]);
  254.         if (c == L'*') {
  255.             star = true;
  256.             pattern += i+1;
  257.             if (!*pattern)
  258.                 return true;
  259.             path += i;
  260.             i = 0;
  261.             continue;
  262.         }
  263.  
  264.         wchar_t d = towlower(path[i]);
  265.         ++i;
  266.  
  267.         if (c == L'?') {        // ? matches any character but null.
  268.             if (!d)
  269.                 return false;
  270.         } else if (c != d) {    // Literal character must match itself.
  271.             // If we're at the end of the string or there is no
  272.             // previous asterisk (anchored search), there's no other
  273.             // match to find.
  274.             if (!star || !d || !i)
  275.                 return false;
  276.  
  277.             // Restart segment search at next position in path.
  278.             ++path;
  279.             i = 0;
  280.             continue;
  281.         }
  282.  
  283.         if (!c)
  284.             return true;
  285.     }
  286. }
  287.  
  288. /////////////////////////////////////////////////////////////////////////////
  289.  
  290. #include <windows.h>
  291. #include <vd2/system/w32assist.h>
  292.  
  293. sint64 VDGetDiskFreeSpace(const wchar_t *path) {
  294.     typedef BOOL (WINAPI *tpGetDiskFreeSpaceExA)(LPCSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailable, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes);
  295.     typedef BOOL (WINAPI *tpGetDiskFreeSpaceExW)(LPCWSTR lpDirectoryName, PULARGE_INTEGER lpFreeBytesAvailable, PULARGE_INTEGER lpTotalNumberOfBytes, PULARGE_INTEGER lpTotalNumberOfFreeBytes);
  296.  
  297.     static bool sbChecked = false;
  298.     static tpGetDiskFreeSpaceExA spGetDiskFreeSpaceExA;
  299.     static tpGetDiskFreeSpaceExW spGetDiskFreeSpaceExW;
  300.  
  301.     if (!sbChecked) {
  302.         HMODULE hmodKernel = GetModuleHandle("kernel32.dll");
  303.         spGetDiskFreeSpaceExA = (tpGetDiskFreeSpaceExA)GetProcAddress(hmodKernel, "GetDiskFreeSpaceExA");
  304.         spGetDiskFreeSpaceExW = (tpGetDiskFreeSpaceExW)GetProcAddress(hmodKernel, "GetDiskFreeSpaceExW");
  305.  
  306.         sbChecked = true;
  307.     }
  308.  
  309.     if (spGetDiskFreeSpaceExA) {
  310.         BOOL success;
  311.         uint64 freeClient, totalBytes, totalFreeBytes;
  312.         VDStringW directoryName(path);
  313.  
  314.         if (!directoryName.empty()) {
  315.             wchar_t c = directoryName[directoryName.length()-1];
  316.  
  317.             if (c != L'/' && c != L'\\')
  318.                 directoryName += L'\\';
  319.         }
  320.  
  321.         if ((LONG)GetVersion() < 0)
  322.             success = spGetDiskFreeSpaceExA(VDTextWToA(directoryName).c_str(), (PULARGE_INTEGER)&freeClient, (PULARGE_INTEGER)&totalBytes, (PULARGE_INTEGER)&totalFreeBytes);
  323.         else
  324.             success = spGetDiskFreeSpaceExW(directoryName.c_str(), (PULARGE_INTEGER)&freeClient, (PULARGE_INTEGER)&totalBytes, (PULARGE_INTEGER)&totalFreeBytes);
  325.  
  326.         return success ? (sint64)freeClient : -1;
  327.     } else {
  328.         DWORD sectorsPerCluster, bytesPerSector, freeClusters, totalClusters;
  329.         BOOL success;
  330.  
  331.         VDStringW rootPath(VDFileGetRootPath(path));
  332.  
  333.         if ((LONG)GetVersion() < 0)
  334.             success = GetDiskFreeSpaceA(rootPath.empty() ? NULL : VDTextWToA(rootPath).c_str(), §orsPerCluster, &bytesPerSector, &freeClusters, &totalClusters);
  335.         else
  336.             success = GetDiskFreeSpaceW(rootPath.empty() ? NULL : rootPath.c_str(), §orsPerCluster, &bytesPerSector, &freeClusters, &totalClusters);
  337.  
  338.         return success ? (sint64)((uint64)sectorsPerCluster * bytesPerSector * freeClusters) : -1;
  339.     }
  340. }
  341.  
  342. bool VDDoesPathExist(const wchar_t *fileName) {
  343.     bool bExists;
  344.  
  345.     if (!(GetVersion() & 0x80000000)) {
  346.         bExists = ((DWORD)-1 != GetFileAttributesW(fileName));
  347.     } else {
  348.         bExists = ((DWORD)-1 != GetFileAttributesA(VDTextWToA(fileName).c_str()));
  349.     }
  350.  
  351.     return bExists;
  352. }
  353.  
  354. void VDCreateDirectory(const wchar_t *path) {
  355.     // can't create dir with trailing slash
  356.     VDStringW::size_type l(wcslen(path));
  357.  
  358.     if (l) {
  359.         const wchar_t c = path[l-1];
  360.  
  361.         if (c == L'/' || c == L'\\') {
  362.             VDCreateDirectory(VDStringW(path, l-1).c_str());
  363.             return;
  364.         }
  365.     }
  366.  
  367.     BOOL succeeded;
  368.  
  369.     if (!(GetVersion() & 0x80000000)) {
  370.         succeeded = CreateDirectoryW(path, NULL);
  371.     } else {
  372.         succeeded = CreateDirectoryA(VDTextWToA(path).c_str(), NULL);
  373.     }
  374.  
  375.     if (!succeeded)
  376.         throw MyWin32Error("Cannot create directory: %%s", GetLastError());
  377. }
  378.  
  379. ///////////////////////////////////////////////////////////////////////////
  380.  
  381. bool VDDeletePathAutodetect(const wchar_t *path);
  382. bool (*VDRemoveFile)(const wchar_t *path) = VDDeletePathAutodetect;
  383.  
  384. namespace {
  385.     typedef BOOL (APIENTRY *tpDeleteFileW)(LPCWSTR path);
  386.     tpDeleteFileW spDeleteFileW;
  387. }
  388.  
  389. bool VDDeleteFile9x(const wchar_t *path) {
  390.     return !!DeleteFileA(VDTextWToA(path).c_str());
  391. }
  392.  
  393. bool VDDeleteFileNT(const wchar_t *path) {
  394.     return !!spDeleteFileW(path);
  395. }
  396.  
  397. bool VDDeletePathAutodetect(const wchar_t *path) {
  398.     if (VDIsWindowsNT()) {
  399.         spDeleteFileW = (tpDeleteFileW)GetProcAddress(GetModuleHandle("kernel32"), "DeleteFileW");
  400.         VDRemoveFile = VDDeleteFileNT;
  401.     } else
  402.         VDRemoveFile = VDDeleteFile9x;
  403.  
  404.     return VDRemoveFile(path);
  405. }
  406.  
  407. ///////////////////////////////////////////////////////////////////////////
  408.  
  409. namespace {
  410.     typedef BOOL (WINAPI *tpGetVolumePathNameW)(LPCWSTR lpszPathName, LPWSTR lpszVolumePathName, DWORD cchBufferLength);
  411.     typedef BOOL (WINAPI *tpGetFullPathNameW)(LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR *lpFilePart);
  412. }
  413.  
  414. VDStringW VDFileGetRootPath(const wchar_t *path) {
  415.     static tpGetVolumePathNameW spGetVolumePathNameW = (tpGetVolumePathNameW)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetVolumePathNameW");
  416.     static tpGetFullPathNameW spGetFullPathNameW = (tpGetFullPathNameW)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetFullPathNameW");
  417.  
  418.     VDStringW fullPath(VDGetFullPath(path));
  419.  
  420.     // Windows 2000/XP path
  421.     if (spGetVolumePathNameW) {
  422.         vdblock<wchar_t> buf(std::max<size_t>(fullPath.size() + 1, MAX_PATH));
  423.  
  424.         if (spGetVolumePathNameW(path, buf.data(), buf.size()))
  425.             return VDStringW(buf.data());
  426.     }
  427.  
  428.     // Windows 95/98/ME/NT4 path
  429.     const wchar_t *s = fullPath.c_str();
  430.     VDStringW root(s, VDFileSplitRoot(s) - s);
  431.     VDFileFixDirPath(root);
  432.     return root;
  433. }
  434.  
  435. VDStringW VDGetFullPath(const wchar_t *partialPath) {
  436.     static tpGetFullPathNameW spGetFullPathNameW = (tpGetFullPathNameW)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetFullPathNameW");
  437.  
  438.     union {
  439.         char        a[MAX_PATH];
  440.         wchar_t        w[MAX_PATH];
  441.     } tmpBuf;
  442.  
  443.     if (spGetFullPathNameW && !(GetVersion() & 0x80000000)) {
  444.         LPWSTR p;
  445.  
  446.         tmpBuf.w[0] = 0;
  447.         DWORD count = spGetFullPathNameW(partialPath, MAX_PATH, tmpBuf.w, &p);
  448.  
  449.         if (count < MAX_PATH)
  450.             return VDStringW(tmpBuf.w);
  451.  
  452.         VDStringW tmp(count);
  453.  
  454.         DWORD newCount = spGetFullPathNameW(partialPath, count, (wchar_t *)tmp.data(), &p);
  455.         if (newCount < count)
  456.             return tmp;
  457.  
  458.         return VDStringW(partialPath);
  459.     } else {
  460.         LPSTR p;
  461.         VDStringA pathA(VDTextWToA(partialPath));
  462.  
  463.         tmpBuf.a[0] = 0;
  464.         DWORD count = GetFullPathNameA(pathA.c_str(), MAX_PATH, tmpBuf.a, &p);
  465.  
  466.         if (count < MAX_PATH)
  467.             return VDStringW(VDTextAToW(tmpBuf.a));
  468.  
  469.         VDStringA tmpA(count);
  470.  
  471.         DWORD newCount = GetFullPathNameA(pathA.c_str(), count, (char *)tmpA.data(), &p);
  472.         if (newCount < count)
  473.             return VDTextAToW(tmpA);
  474.  
  475.         return VDStringW(partialPath);
  476.     }
  477. }
  478.  
  479. VDStringW VDMakePath(const wchar_t *base, const wchar_t *file) {
  480.     if (!*base)
  481.         return VDStringW(file);
  482.  
  483.     VDStringW result(base);
  484.  
  485.     const wchar_t c = result[result.size() - 1];
  486.  
  487.     if (c != L'/' && c != L'\\' && c != L':')
  488.         result += L'\\';
  489.  
  490.     result.append(file);
  491.  
  492.     return result;
  493. }
  494.  
  495. void VDFileFixDirPath(VDStringW& path) {
  496.     if (!path.empty()) {
  497.         wchar_t c = path[path.size()-1];
  498.  
  499.         if (c != L'/' && c != L'\\' && c != L':')
  500.             path += L'\\';
  501.     }
  502. }
  503.  
  504. VDStringW VDGetProgramPath() {
  505.     union {
  506.         wchar_t w[MAX_PATH];
  507.         char a[MAX_PATH];
  508.     } buf;
  509.  
  510.     VDStringW wstr;
  511.  
  512.     if (VDIsWindowsNT()) {
  513.         wcscpy(buf.w, L".");
  514.         if (GetModuleFileNameW(NULL, buf.w, MAX_PATH))
  515.             *VDFileSplitPath(buf.w) = 0;
  516.         wstr = buf.w;
  517.     } else {
  518.         strcpy(buf.a, ".");
  519.         if (GetModuleFileNameA(NULL, buf.a, MAX_PATH))
  520.             *VDFileSplitPath(buf.a) = 0;
  521.         wstr = VDTextAToW(buf.a, -1);
  522.     }
  523.  
  524.     VDStringW wstr2(VDGetFullPath(wstr.c_str()));
  525.  
  526.     return wstr2;
  527. }
  528.  
  529. ///////////////////////////////////////////////////////////////////////////
  530.  
  531. VDDirectoryIterator::VDDirectoryIterator(const wchar_t *path)
  532.     : mSearchPath(path)
  533.     , mpHandle(NULL)
  534.     , mbSearchComplete(false)
  535. {
  536.     mBasePath = VDFileSplitPathLeft(mSearchPath);
  537.     VDFileFixDirPath(mBasePath);
  538. }
  539.  
  540. VDDirectoryIterator::~VDDirectoryIterator() {
  541.     if (mpHandle)
  542.         FindClose((HANDLE)mpHandle);
  543. }
  544.  
  545. bool VDDirectoryIterator::Next() {
  546.     if (mbSearchComplete)
  547.         return false;
  548.  
  549.     union {
  550.         WIN32_FIND_DATAA a;
  551.         WIN32_FIND_DATAW w;
  552.     } wfd;
  553.  
  554.     if (GetVersion() & 0x80000000) {
  555.         if (mpHandle)
  556.             mbSearchComplete = !FindNextFileA((HANDLE)mpHandle, &wfd.a);
  557.         else {
  558.             mpHandle = FindFirstFileA(VDTextWToA(mSearchPath).c_str(), &wfd.a);
  559.             mbSearchComplete = (INVALID_HANDLE_VALUE == mpHandle);
  560.         }
  561.         if (mbSearchComplete)
  562.             return false;
  563.  
  564.         mbDirectory = (wfd.a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
  565.         mFilename = VDTextAToW(wfd.a.cFileName);
  566.         mFileSize = wfd.a.nFileSizeLow + ((sint64)wfd.w.nFileSizeHigh << 32);
  567.     } else {
  568.         if (mpHandle)
  569.             mbSearchComplete = !FindNextFileW((HANDLE)mpHandle, &wfd.w);
  570.         else {
  571.             mpHandle = FindFirstFileW(mSearchPath.c_str(), &wfd.w);
  572.             mbSearchComplete = (INVALID_HANDLE_VALUE == mpHandle);
  573.         }
  574.         if (mbSearchComplete)
  575.             return false;
  576.  
  577.         mbDirectory = (wfd.w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
  578.         mFilename = wfd.w.cFileName;
  579.         mFileSize = wfd.w.nFileSizeLow + ((sint64)wfd.w.nFileSizeHigh << 32);
  580.     }
  581.  
  582.     return true;
  583. }
  584.  
  585. ///////////////////////////////////////////////////////////////////////////
  586.  
  587. #ifdef _DEBUG
  588.  
  589. struct VDSystemFilesysTestObject {
  590.     VDSystemFilesysTestObject() {
  591. #define TEST(fn, x, y1, y2) VDASSERT(!strcmp(fn(x), y2)); VDASSERT(!wcscmp(fn(L##x), L##y2)); VDASSERT(fn##Left(VDStringA(x))==y1); VDASSERT(fn##Right(VDStringA(x))==y2); VDASSERT(fn##Left(VDStringW(L##x))==L##y1); VDASSERT(fn##Right(VDStringW(L##x))==L##y2)
  592.         TEST(VDFileSplitPath, "", "", "");
  593.         TEST(VDFileSplitPath, "x", "", "x");
  594.         TEST(VDFileSplitPath, "x\\y", "x\\", "y");
  595.         TEST(VDFileSplitPath, "x\\y\\z", "x\\y\\", "z");
  596.         TEST(VDFileSplitPath, "x\\", "x\\", "");
  597.         TEST(VDFileSplitPath, "x\\y\\z\\", "x\\y\\z\\", "");
  598.         TEST(VDFileSplitPath, "c:", "c:", "");
  599.         TEST(VDFileSplitPath, "c:x", "c:", "x");
  600.         TEST(VDFileSplitPath, "c:\\", "c:\\", "");
  601.         TEST(VDFileSplitPath, "c:\\x", "c:\\", "x");
  602.         TEST(VDFileSplitPath, "c:\\x\\", "c:\\x\\", "");
  603.         TEST(VDFileSplitPath, "c:\\x\\", "c:\\x\\", "");
  604.         TEST(VDFileSplitPath, "c:x\\y", "c:x\\", "y");
  605.         TEST(VDFileSplitPath, "\\\\server\\share\\", "\\\\server\\share\\", "");
  606.         TEST(VDFileSplitPath, "\\\\server\\share\\x", "\\\\server\\share\\", "x");
  607. #undef TEST
  608. #define TEST(fn, x, y1, y2) VDASSERT(!strcmp(fn(x), y2)); VDASSERT(!wcscmp(fn(L##x), L##y2)); VDASSERT(fn(VDStringA(x))==y1); VDASSERT(fn(VDStringW(L##x))==L##y1)
  609.         TEST(VDFileSplitRoot, "", "", "");
  610.         TEST(VDFileSplitRoot, "c:", "c:", "");
  611.         TEST(VDFileSplitRoot, "c:x", "c:", "x");
  612.         TEST(VDFileSplitRoot, "c:x\\", "c:", "x\\");
  613.         TEST(VDFileSplitRoot, "c:x\\y", "c:", "x\\y");
  614.         TEST(VDFileSplitRoot, "c:\\", "c:\\", "");
  615.         TEST(VDFileSplitRoot, "c:\\x", "c:\\", "x");
  616.         TEST(VDFileSplitRoot, "c:\\x\\", "c:\\", "x\\");
  617.         TEST(VDFileSplitRoot, "\\", "\\", "");
  618.         TEST(VDFileSplitRoot, "\\x", "\\", "x");
  619.         TEST(VDFileSplitRoot, "\\x\\", "\\", "x\\");
  620.         TEST(VDFileSplitRoot, "\\x\\y", "\\", "x\\y");
  621.         TEST(VDFileSplitRoot, "\\\\server\\share", "\\\\server\\share", "");
  622.         TEST(VDFileSplitRoot, "\\\\server\\share\\", "\\\\server\\share\\", "");
  623.         TEST(VDFileSplitRoot, "\\\\server\\share\\x", "\\\\server\\share\\", "x");
  624.         TEST(VDFileSplitRoot, "\\\\server\\share\\x\\", "\\\\server\\share\\", "x\\");
  625.         TEST(VDFileSplitRoot, "\\\\server\\share\\x\\y", "\\\\server\\share\\", "x\\y");
  626. #undef TEST
  627.     }
  628. } g_VDSystemFilesysTestObject;
  629.  
  630. #endif
  631.